package org.example.semaphore;

import lombok.extern.slf4j.Slf4j;
import org.example.finalobj.MockConnection;

import java.sql.Connection;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicIntegerArray;

/**
 * @author ZhengDp
 * @Date 2023/2/19 21:22
 */
public class SemaphoreExample {
}

/**
 * 连接池对象
 */
@Slf4j(topic = "c.Pool")
class Pool {
    // 连接池大小 (一般的连接池支持 扩容和收缩）
    private final int poolSize;

    // 连接对象数组
    private Connection[] connections;

    // 连接状态数组 （0:空闲 1:繁忙)
    private AtomicIntegerArray states;

    private Semaphore semaphore;

    public Pool(int poolSize) {
        this.poolSize = poolSize;
        connections = new Connection[poolSize];
        // 信号量许可数 与 资源数 一致
        semaphore = new Semaphore(poolSize);
        this.states = new AtomicIntegerArray(new int[poolSize]);
        for (int i = 0; i < poolSize; i++) {
            connections[i] = new MockConnection("连接" + (i + 1));
        }
    }

    /**
     * 获取连接对象
     *
     * @return
     */
    public Connection borrow() {
        try {
            // 有许可才会去 寻找空闲连接
            semaphore.acquire(); // ==> 没有许可的线程，在此等待
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        for (int i = 0; i < poolSize; i++) {
            if (states.get(i) == 0) {
                // 2. 重新设置连接数组状态
                if (states.compareAndSet(i, 0, 1)) {
                    log.info("borrow {}", connections[i]);
                    return connections[i];
                }
            }
        }

        // 不会执行到该行代码
        return null;
    }

    /**
     * 归还连接对象
     *
     * @param connection
     */
    public void free(Connection connection) {
        for (int i = 0; i < poolSize; i++) {
            if (connections[i] == connection) {
                // 设置连接状态
                states.set(i, 0);
                log.info("free {}" , connection);
                semaphore.release();
                break;
            }
        }
    }
}


